from Bases import setID
from osc_base import OSCBaseObject

class DummyBase(object):
    def __init__(self, **kwargs):
        object.__init__(self)
        return kwargs

class NormalAttribute(DummyBase):
    _saved_class_name = 'NormalAttribute'
    uiTypeName = 'Normal'
    def __init__(self, metacls, **kwargs):
        if not hasattr(self, 'base_class'):
            self.base_class = metacls.__name__
        metacls.__init__(self, **kwargs)
    
class IndexedParameter(OSCBaseObject):
    _saved_class_name = 'IndexedParameter'
    _saved_attributes = ['name', 'id', 'parent_attribute_id', 'val_min', 'val_max']
    def __init__(self, **kwargs):
        super(IndexedParameter, self).__init__(**kwargs)
        
        if 'deserialize' not in kwargs:
            self.name = kwargs.get('name', '')
            self.id = setID(kwargs.get('id', None))
            self.parent_attribute_id = kwargs.get('parent_attribute_id')
            self.val_min = int(kwargs.get('val_min', 0))
            self.val_max = int(kwargs.get('val_max', 1))
        self.range_str = str(self.val_min) + ' - ' + str(self.val_max)
        self.register_attr_watch('name')
        self.register_attr_watch('val_min')
        self.register_attr_watch('val_max')
    def is_active(self, value):
        if value >= self.val_min and value <= self.val_max:
            return True

class IndexedAttribute(DummyBase):
    '''An attribute that handles values in ranges
        (control, gobo/litho, effects wheels, etc.)
    
    :Parameters:
        'parameters' : list of parameters to be added.  elements in the list
            will be the same as kwargs for the add_parameter method.
            ([{name:'param1',val_min:0,val_max:10},{name:'param2',val_min:11,val_max:20}])
            default is None.
        'from_xml' : xml string which, if specified, the xml will be loaded
            into the attribute.  default is None.
    
    :Events:
        'new_parameter' (attribute_id, parameter_id)
        'parameter_changed' (attribute, name)
            name is the name of the new active parameter,
            or None if nothing is active.
    '''
    
    _saved_class_name = 'IndexedAttribute'
    _saved_child_objects = ['parameters']
    _saved_child_classes = [IndexedParameter]
    uiTypeName = 'Indexed'
    def __init__(self, metacls, **kwargs):
        if hasattr(self, 'base_class') is False:
            self.base_class = metacls.__name__
        metacls.__init__(self, **kwargs)
        
        if 'deserialize' not in kwargs:
            params = kwargs.get('parameters')
            self.parameters = {}
            if params is not None:
                for param in params.itervalues():
                    self.add_parameter(**param.__dict__)
        self.active_index = None
        if not hasattr(self, 'parameters'):
            self.parameters = {}
        self._find_active_parameter()
        self.register_signal('new_parameter', 'parameter_changed')
        #self.uiTypeName = 'Indexed'
        
    def add_parameter(self, **kwargs):
        '''Add a parameter index
        :Parameters:
            'name' : str, the name visible in the UI when the new parameter is active.
                NOT also used as a dictionary key.
            'val_min' : int, minimum value for the new parameter to be active.
            'val_max' : int, maximum value for the new parameter to be active.
        '''
        #name = kwargs.get('name')
        kwargs.update({'parent_attribute_id':self.id})
        self.add_child_object(**kwargs)
        parameter = IndexedParameter(**kwargs)
        self.parameters.update({parameter.id:parameter})
        if hasattr(self, 'id') and 'new_parameter' in self._emitters:
            self.emit('new_parameter', attribute_id=self.id, parameter_id=parameter.id)
        return parameter

    def on_value_change(self):
        super(IndexedAttribute, self).on_value_change()
        self._find_active_parameter()
        
    def set_parameter(self, name):
        if hasattr(self, 'value'):
            if name in self.parameters:
                self.value = self.parameters[name].val_min
        
    def _find_active_parameter(self):
        if hasattr(self, 'value'):
            active_index = None
            for key, val in self.parameters.iteritems():
                if val is not None:
                    if val.is_active(self.value):
                        active_index = key
            if active_index != self.active_index:
                self.active_index = active_index
                self.emit('parameter_changed', attribute=self, name=active_index)
                
